import asyncio
import os
import sys
import socket
import psutil
import signal
import time

# 添加项目根目录到Python路径
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)

import uvicorn
from sqlalchemy.ext.asyncio import create_async_engine
# 直接导入base模块，避免通过db包的导入链
from db.models.base import Base
from config.settings import settings
from dotenv import load_dotenv

# 清理可能影响openai客户端的代理环境变量
def clean_proxy_env():
    """清理代理环境变量，避免openai客户端初始化问题"""
    proxy_vars = ['HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy', 'NO_PROXY', 'no_proxy']
    for var in proxy_vars:
        if var in os.environ:
            print(f"清理代理环境变量: {var}")
            del os.environ[var]

# 在加载其他模块前清理代理环境变量
clean_proxy_env()

# 加载 .env 文件
load_dotenv(os.path.join(os.path.dirname(__file__), ".env"))

os.environ["NLTK_DATA"] = "/usr/local/nltk_data"


def is_port_in_use(port: int) -> bool:
    """检查端口是否被占用"""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        return s.connect_ex(('localhost', port)) == 0


def kill_process_on_port(port: int):
    """终止占用指定端口的进程"""
    for proc in psutil.process_iter(['pid', 'name']):
        try:
            # 使用更兼容的方式获取连接信息
            try:
                connections = proc.connections()
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess, AttributeError):
                continue
                
            for conn in connections:
                if hasattr(conn, 'laddr') and conn.laddr and conn.laddr.port == port:
                    print(f"终止进程 {proc.pid} ({proc.name()})")
                    os.kill(proc.pid, signal.SIGTERM)
                    time.sleep(1)  # 等待进程终止
                    break
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess, AttributeError):
            pass


async def init_db():
    """初始化数据库"""
    print("正在初始化数据库...")
    try:
        engine = create_async_engine(settings.DATABASE_URL, echo=settings.DEBUG)
        async with engine.begin() as conn:
            await conn.run_sync(Base.metadata.create_all)
        print("数据库初始化完成！")
    except Exception as e:
        print(f"⚠️  数据库连接失败: {e}")
        print("⚠️  应用将继续启动，但数据库功能可能不可用")
        print("⚠️  请检查数据库配置: config/settings.py")
        # 不退出，让应用继续启动

def init_db_sync():
    """同步初始化数据库"""
    print("正在初始化数据库...")
    try:
        # 检查是否已有运行中的事件循环
        try:
            loop = asyncio.get_running_loop()
            # 如果已有运行中的循环，使用异步方式
            print("检测到运行中的事件循环，跳过数据库初始化...")
            print("数据库将在应用启动后自动初始化")
            return
        except RuntimeError:
            # 没有运行中的循环，创建新的
            pass
        
        # 使用同步方式初始化数据库
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            loop.run_until_complete(init_db())
        finally:
            loop.close()
    except Exception as e:
        print(f"⚠️  数据库初始化失败: {e}")
        print("⚠️  应用将继续启动，但数据库功能可能不可用")


def check_dependencies():
    """检查必要的依赖是否已安装"""
    print("正在检查依赖...")
    try:
        import fastapi
        import uvicorn
        import sqlalchemy
        import aiomysql
        import pydantic
        import requests
        import psutil
        print("所有依赖已安装！")
    except ImportError as e:
        print(f"缺少必要的依赖: {e}")
        print("请运行: pip install -r requirements.txt")
        sys.exit(1)


def check_environment():
    """检查环境配置"""
    print("正在检查环境配置...")
    print("当前工作目录:", os.getcwd())
    print("环境文件路径:", os.path.join(os.path.dirname(__file__), ".env"))

    # 检查数据库配置
    db_vars = ["DB_USER", "DB_PASSWORD", "DB_HOST", "DB_PORT", "DB_NAME"]
    print("\n数据库配置:")
    for var in db_vars:
        value = os.getenv(var, getattr(settings, var, "未设置"))
        if var == "DB_PASSWORD":
            print(f"{var}: *** (已设置)")
        else:
            print(f"{var}: {value}")

    # 检查AI配置
    ai_vars = ["AI_PROVIDER", "AI_CHAT_URL", "AI_USERNAME", "AI_PASSWORD"]
    print("\nAI配置:")
    for var in ai_vars:
        value = os.getenv(var, getattr(settings, var, "未设置"))
        if var == "AI_PASSWORD":
            print(f"{var}: *** (已设置)")
        else:
            print(f"{var}: {value}")

    # 检查关键配置是否可用
    try:
        # 测试数据库URL构建
        db_url = settings.DATABASE_URL
        print(f"\n数据库URL: {db_url.replace(settings.DB_PASSWORD, '***')}")
        
        # 测试AI配置
        print(f"AI提供商: {settings.AI_PROVIDER}")
        print(f"AI聊天URL: {settings.AI_CHAT_URL}")
        
        # 检查是否需要修改配置
        if "your_password" in settings.DB_PASSWORD or "your_db_host" in settings.DB_HOST:
            print("\n⚠️  检测到默认配置，请修改以下配置:")
            if "your_password" in settings.DB_PASSWORD:
                print("   - DB_PASSWORD: 请设置正确的数据库密码")
            if "your_db_host" in settings.DB_HOST:
                print("   - DB_HOST: 请设置正确的数据库主机地址")
            print("   修改方法: 编辑 config/settings.py 文件")
            print("   修改后需要重新构建镜像")
            print("   注意: 使用默认配置时数据库功能不可用")
        else:
            print("\n✅ 配置检查通过，数据库配置已设置")
        
        print("环境配置检查完成！")
    except Exception as e:
        print(f"\n环境配置检查失败: {e}")
        print("请检查数据库和AI服务配置")
        sys.exit(1)


def start_service():
    """启动服务"""
    print(f"正在启动 {settings.APP_NAME} 服务...")

    # 检查端口是否被占用
    port = 8000
    if is_port_in_use(port):
        print(f"端口 {port} 已被占用，尝试释放...")
        kill_process_on_port(port)
        time.sleep(2)  # 等待端口释放

    # 检测是否为生产环境
    is_production = os.getenv("ENVIRONMENT", "development") == "production"
    
    if is_production:
        print("检测到生产环境，使用生产配置...")
        # 生产环境配置
        uvicorn.run(
            "api.main:app",
            host="0.0.0.0",
            port=port,
            reload=False,  # 生产环境禁用自动重载
            log_level="info",
            workers=1,  # 生产环境使用单进程
            access_log=True,
            use_colors=False,  # 生产环境禁用颜色
            limit_concurrency=1000,  # 限制并发连接数
            limit_max_requests=10000,  # 限制最大请求数
            timeout_keep_alive=30,  # 保持连接超时
            timeout_graceful_shutdown=30,  # 优雅关闭超时
        )
    else:
        print("检测到开发环境，使用开发配置...")
        # 开发环境配置
        uvicorn.run(
            "api.main:app",
            host="0.0.0.0",
            port=port,
            reload=True,  # 开发环境启用自动重载
            log_level="info"
        )


def main():
    """主函数"""
    print(f"=== {settings.APP_NAME} 启动程序 ===")

    # 1. 检查依赖
    check_dependencies()

    # 2. 检查环境变量
    check_environment()

    # 3. 跳过数据库初始化（手动管理数据库表）
    print("跳过数据库初始化，使用手动管理的数据库表")

    # 4. 启动服务
    start_service()


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n服务已停止")
    except Exception as e:
        print(f"启动失败: {e}")
        sys.exit(1)

